package com.bluechiz.tube.youtube
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	import flash.system.Security;
	
	import mx.containers.Canvas;
	import mx.controls.Button;
	import mx.controls.ComboBox;
	import mx.controls.SWFLoader;
	import mx.controls.TextInput;
	import mx.events.ListEvent;
	import mx.events.StateChangeEvent;
	
	public class TubePlayer extends Canvas {
		// Member variables.
		private var cueButton:Button;
		private var isQualityPopulated:Boolean;
		private var isWidescreen:Boolean;
		private var pauseButton:Button;
		private var playButton:Button;
		private var player:Object;
		private var playerLoader:SWFLoader;
		private var qualityComboBox:ComboBox;
		private var videoIdTextInput:TextInput;
		private var youtubeApiLoader:URLLoader;
		
		private var state:Number = -1;
		private var videoId:String;
		
		// CONSTANTS.
		private static const DEFAULT_VIDEO_ID:String = "0QRO3gKj3qw";
		private static const PLAYER_URL:String =
		"http://www.youtube.com/apiplayer?version=3";
		private static const SECURITY_DOMAIN:Array = new Array(
			"http://www.youtube.com",
			"youtube.com",
			"s.ytimg.com", 
			"i.ytimg.com"
		)
		private static const YOUTUBE_API_PREFIX:String =
			"http://gdata.youtube.com/feeds/api/videos/";
		private static const YOUTUBE_API_VERSION:String = "2";
		private static const YOUTUBE_API_FORMAT:String = "5";
		private static const WIDESCREEN_ASPECT_RATIO:String = "widescreen";
		private static const QUALITY_TO_PLAYER_WIDTH:Object = {
			small: 320,
			medium: 640,
			large: 854, 
			hd720: 1280
		};
		private static const STATE_ENDED:Number = 0;
		private static const STATE_PLAYING:Number = 1;
		private static const STATE_PAUSED:Number = 2;
		private static const STATE_CUED:Number = 5;
		private static const STATE_READY:Number = 10;
		
		public function TubePlayer():void {
			// Specifically allow the chromless player .swf access to our .swf.
			
			//		for each (var domain:String in SECURITY_DOMAIN) {
			//      		Security.allowDomain(domain);
			//		}
			
			//Security.allowDomain("*");
			
			setupUi();
			setupPlayerLoader();
			setupYouTubeApiLoader();
		}
		
		private function setupUi():void {
			// Create a TextInput field for the YouTube video id, and pre-populate it.
			videoIdTextInput = new TextInput();
			videoIdTextInput.text = DEFAULT_VIDEO_ID;
			videoIdTextInput.width = 100;
			videoIdTextInput.x = 10;
			videoIdTextInput.y = 10;
			addChild(videoIdTextInput);
			
			// Create a Button for cueing up the video whose id is specified.
			//      cueButton = new Button();
			//      cueButton.enabled = false;
			//      cueButton.label = "Cue Video";
			//      cueButton.width = 100;
			//      cueButton.x = 120;
			//      cueButton.y = 10;
			//      cueButton.addEventListener(MouseEvent.CLICK, cueButtonClickHandler);
			//      addChild(cueButton);
			
			// Create a ComboBox that will contain the list of available playback
			// qualities. Selecting from the ComboBox will change the playback quality
			// and resize the player. Note that playback qualities are only available
			// once a video has started playing, so the values in this ComboBox can't
			// be populated until then.
			qualityComboBox = new ComboBox();
			qualityComboBox.prompt = "n/a";
			qualityComboBox.width = 100;
			qualityComboBox.x = 230;
			qualityComboBox.y = 10;
			qualityComboBox.addEventListener(ListEvent.CHANGE,
				qualityComboBoxChangeHandler);
			addChild(qualityComboBox);
			
			// Create a Button for playing the cued video.
			//      playButton = new Button();
			//      playButton.enabled = false;
			//      playButton.label = "Play";
			//      playButton.width = 100;
			//      playButton.x = 340;
			//      playButton.y = 10;
			//      playButton.addEventListener(MouseEvent.CLICK, playButtonClickHandler);
			//      addChild(playButton);
			
			// Create a Button for pausing the cued video.
			//      pauseButton = new Button();
			//      pauseButton.enabled = false;
			//      pauseButton.label = "Pause";
			//      pauseButton.width = 100;
			//      pauseButton.x = 450;
			//      pauseButton.y = 10;
			//      pauseButton.addEventListener(MouseEvent.CLICK, pauseButtonClickHandler);
			//      addChild(pauseButton);
		}
		
		private function setupPlayerLoader():void {
			playerLoader = new SWFLoader();
			playerLoader.addEventListener(Event.INIT, playerLoaderInitHandler);
			playerLoader.load(PLAYER_URL);
		}
		
		private function playerLoaderInitHandler(event:Event):void {
			addChild(playerLoader);
			playerLoader.content.addEventListener("onReady", onPlayerReady);
			playerLoader.content.addEventListener("onError", onPlayerError);
			playerLoader.content.addEventListener("onStateChange",
				onPlayerStateChange);
			playerLoader.content.addEventListener("onPlaybackQualityChange",
				onVideoPlaybackQualityChange);
		}
		
		private function setupYouTubeApiLoader():void {
			youtubeApiLoader = new URLLoader();
			youtubeApiLoader.addEventListener(IOErrorEvent.IO_ERROR,
				youtubeApiLoaderErrorHandler);
			youtubeApiLoader.addEventListener(Event.COMPLETE,
				youtubeApiLoaderCompleteHandler);
		}
		
		private function youtubeApiLoaderCompleteHandler(event:Event):void {
			var atomData:String = youtubeApiLoader.data;
			
			// Parse the YouTube API XML response and get the value of the
			// aspectRatio element.
			var atomXml:XML = new XML(atomData);
			var aspectRatios:XMLList = atomXml..*::aspectRatio;
			
			isWidescreen = aspectRatios.toString() == WIDESCREEN_ASPECT_RATIO;
			
			isQualityPopulated = false;
			// Cue up the video once we know whether it's widescreen.
			// Alternatively, you could start playing instead of cueing with
			// player.loadVideoById(videoIdTextInput.text);
			player.cueVideoById(this.videoId);
		}
		
		private function qualityComboBoxChangeHandler(event:Event):void {
			var qualityLevel:String = ComboBox(event.target).selectedLabel;
			player.setPlaybackQuality(qualityLevel);
		}
		
		public function load (videoId:String):void {
			this.videoId = videoId;
			var request:URLRequest = new URLRequest(YOUTUBE_API_PREFIX +
				this.videoId);
			
			var urlVariables:URLVariables = new URLVariables();
			urlVariables.v = YOUTUBE_API_VERSION;
			urlVariables.format = YOUTUBE_API_FORMAT;
			request.data = urlVariables;
			
			try {
				youtubeApiLoader.load(request);
			} catch (error:SecurityError) {
				trace("A SecurityError occurred while loading", request.url);
			}
		}
		
		public function play():void {
			player.playVideo();
		}
		
		public function pause():void {
			player.pauseVideo();
		}
		
		public function stop():void {
			player.stopVideo();
		}
		
		private function youtubeApiLoaderErrorHandler(event:IOErrorEvent):void {
			trace("Error making YouTube API request:", event);
		}
		
		private function onPlayerReady(event:Event):void {
			player = playerLoader.content;
			player.visible = false;
			
			var event:Event = new StateChangeEvent() {
				
			};
			Object(event).data = 10;
			onPlayerStateChange(event);
			//      cueButton.enabled = true;
		}
		
		private function onPlayerError(event:Event):void {
			trace("Player error:", Object(event).data);
		}
		
		private function onPlayerStateChange(event:Event):void {
			trace("State is", Object(event).data);
			
			state = Object(event).data;
			dispatchEvent(event);
//			switch (Object(event).data) {
//				case STATE_ENDED:
//					playButton.enabled = true;
//					pauseButton.enabled = false;
//					break;
//				
//				case STATE_PLAYING:
//					//          playButton.enabled = false;
//					//          pauseButton.enabled = true;
//					
//					if(!isQualityPopulated) {
//						populateQualityComboBox();
//					}
//					break;
//				
//				case STATE_PAUSED:
//					//          playButton.enabled = true;
//					//          pauseButton.enabled = false;
//					break;
//				
//				case STATE_CUED:
//					//          playButton.enabled = true;
//					//          pauseButton.enabled = false;
//					
//					resizePlayer("medium");
//					break;
//			}
		}
		
		private function onVideoPlaybackQualityChange(event:Event):void {
			trace("Current video quality:", Object(event).data);
			resizePlayer(Object(event).data);
		}
		
		private function resizePlayer(qualityLevel:String):void {
			var newWidth:Number = QUALITY_TO_PLAYER_WIDTH[qualityLevel] || 640;
			var newHeight:Number;
			
			if (isWidescreen) {
				// Widescreen videos (usually) fit into a 16:9 player.
				newHeight = newWidth * 9 / 16;
			} else {
				// Non-widescreen videos fit into a 4:3 player.
				newHeight = newWidth * 3 / 4;
			}
			
			trace("isWidescreen is", isWidescreen, ". Size:", newWidth, newHeight);
			player.setSize(newWidth, newHeight);
			
			// Center the resized player on the stage.
			player.x = (stage.stageWidth - newWidth) / 2;
			player.y = (stage.stageHeight - newHeight) / 2;
			
			player.visible = true;
		}
		
		private function populateQualityComboBox():void {
			isQualityPopulated = true;
			
			var qualities:Array = player.getAvailableQualityLevels();
			qualityComboBox.dataProvider = qualities;
			
			var currentQuality:String = player.getPlaybackQuality();
			qualityComboBox.selectedItem = currentQuality;
		}
	}
}